﻿using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Imgur.Net.Auth;
using NUnit.Framework;

namespace Imgur.Net.Test.Auth
{
    [TestFixture]
    public class RefreshTokenInvalidExceptionTests
    {
        [Test]
        public void CreateInstanceTest()
        {
            var instance = new RefreshTokenInvalidException();
            Assert.IsNotNull(instance);
        }

        [Test]
        public void CreateInstanceStringTest()
        {
            const string message = "exception message";

            var instance = new RefreshTokenInvalidException(message);
            Assert.IsNotNull(instance);

            Assert.AreEqual(message, instance.Message);
        }
        
        [Test]
        public void CreateInstanceStringInnerExceptionTest()
        {
            const string message = "exception message";
            Exception inner = new Exception("inner exception");

            var instance = new RefreshTokenInvalidException(message, inner);
            Assert.IsNotNull(instance);

            Assert.AreEqual(message, instance.Message);            
            Assert.AreEqual(inner, instance.InnerException);
        }

        [Test]
        public void CreateInstanceSerializationTest()
        {
            const string message = "exception message";

            var instance = new RefreshTokenInvalidException(message);
            Assert.IsNotNull(instance);

            Assert.AreEqual(message, instance.Message);

            RefreshTokenInvalidException afterDeserializationException;

            using (Stream s = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(s, instance);
                s.Position = 0; // Reset stream position
                afterDeserializationException = (RefreshTokenInvalidException)formatter.Deserialize(s);
            }

            Assert.IsNotNull(afterDeserializationException);
            Assert.AreEqual(instance, afterDeserializationException);
        }

        [Test]
        public void EqualsObjVsNullTest()
        {
            const string message = "exception message";
            Exception inner = new Exception("inner exception");

            var instance = new RefreshTokenInvalidException(message, inner);
            Assert.IsNotNull(instance);

            Assert.IsFalse(instance.Equals(null));
        }

        [Test]
        public void EqualsObjVsSameObjectTest()
        {
            const string message = "exception message";
            Exception inner = new Exception("inner exception");

            var instance = new RefreshTokenInvalidException(message, inner);
            Assert.IsNotNull(instance);

            Assert.IsTrue(instance.Equals(instance));
        }

        [Test]
        public void EqualsObjVsDifferentTypeTest()
        {
            const string message = "exception message";
            Exception inner = new Exception("inner exception");

            var instance = new RefreshTokenInvalidException(message, inner);

            var other = new Exception("other excpetion");

            Assert.IsNotNull(instance);
            Assert.IsNotNull(other);

            Assert.IsFalse(instance.Equals(other));
        }

        [Test]
        public void EqualsObjVsIdenticalObjectTest()
        {
            const string message = "exception message";
            Exception inner = new Exception("inner exception");

            var instance = new RefreshTokenInvalidException(message, inner);
            var other = new RefreshTokenInvalidException(message, inner);

            Assert.IsNotNull(instance);
            Assert.IsNotNull(other);

            Assert.IsTrue(instance.Equals(other));
        }

        [Test]
        public void HashCodeIdenticalObjectsTest()
        {
            const string message = "exception message";
            Exception inner = new Exception("inner exception");

            var instance = new RefreshTokenInvalidException(message, inner);
            var other = new RefreshTokenInvalidException(message, inner);

            Assert.IsNotNull(instance);
            Assert.IsNotNull(other);

            int instanceHashCode = instance.GetHashCode();
            int otherHashCode = other.GetHashCode();

            Assert.AreEqual(instanceHashCode, otherHashCode);
        }

        [Test]
        public void HashCodeRepeatedCallsTest()
        {
            const string message = "exception message";
            Exception inner = new Exception("inner exception");

            var instance = new RefreshTokenInvalidException(message, inner);

            Assert.IsNotNull(instance);

            int instanceHashCode = instance.GetHashCode();

            for (int i = 0; i < 10; ++i)
            {
                Assert.AreEqual(instanceHashCode, instance.GetHashCode());
            }
        }

        [Test]
        public void HashCodeDifferentStateTest()
        {
            const string message = "exception message";
            const string otherMessage = "other message";
            Exception inner = new Exception("inner exception");

            var instance = new RefreshTokenInvalidException(message, inner);
            var other = new RefreshTokenInvalidException(otherMessage);

            Assert.IsNotNull(instance);
            Assert.IsNotNull(other);

            int instanceHashCode = instance.GetHashCode();
            int otherHashCode = other.GetHashCode();

            Assert.AreNotEqual(instanceHashCode, otherHashCode);
        }

        [Test]
        public void EqualsOperatorTest()
        {
            const string message = "exception message";
            Exception inner = new Exception("inner exception");

            var instance = new RefreshTokenInvalidException(message, inner);
            var other = new RefreshTokenInvalidException(message, inner);

            Assert.IsNotNull(instance);
            Assert.IsNotNull(other);

            Assert.IsTrue(instance == other);
        }

        [Test]
        public void NotEqualsOperatorTest()
        {
            const string message = "exception message";
            const string otherMessage = "other message";
            Exception inner = new Exception("inner exception");

            var instance = new RefreshTokenInvalidException(message, inner);
            var other = new RefreshTokenInvalidException(otherMessage);

            Assert.IsNotNull(instance);
            Assert.IsNotNull(other);

            Assert.IsTrue(instance != other);

        }
    }
}
